package shoppingcart

import (
	"context"
	"time"

	"mall/common/globalkey"
	"mall/common/resultx"
	"mall/service/backend/common/i18n"
	"mall/service/order/model"
	"mall/service/order/rpc/internal/svc"
	"mall/service/order/rpc/internal/utils/errorhandler"
	"mall/service/order/rpc/types/order"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type BatchUpdateShoppingCartLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBatchUpdateShoppingCartLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BatchUpdateShoppingCartLogic {
	return &BatchUpdateShoppingCartLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BatchUpdateShoppingCartLogic) BatchUpdateShoppingCart(in *order.BatchUpdateShoppingCartReq) (*order.BaseResp, error) {
	if in.UserId == nil || *in.UserId == 0 {
		return nil, resultx.StatusError(resultx.USER_ID_REQUIRED, "")
	}

	var skuIds []any
	skuIdQtyMap := make(map[uint64]*order.ShoppingCartSpecialInfo)
	for skuId, v := range in.SkuQtyMap {
		skuIds = append(skuIds, skuId)
		skuIdQtyMap[skuId] = v
	}
	if len(skuIds) == 0 {
		return nil, resultx.StatusError(resultx.PRODUCT_VARIATION_ID_REQUIRED, "")
	}

	userId := *in.UserId
	var orderId uint64
	if in.OrderId != nil && *in.OrderId > 0 {
		orderId = *in.OrderId
	}
	now := time.Now()

	filterMap := make(map[string]map[string][]any)
	filterMap[model.CartItemColumns.UserID] = map[string][]any{
		"equalTo": {userId},
	}
	filterMap[model.CartItemColumns.Status] = map[string][]any{
		"equalTo": {globalkey.StatusEnabled},
	}
	filterMap[model.CartItemColumns.SkuID] = map[string][]any{
		"in": skuIds,
	}
	list, _, err := l.svcCtx.Cart.GetList(l.ctx, model.M{}, -1, filterMap)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.ORDER_UPDATE_CART_FAILED, "")
	}

	if len(list) > 0 {
		for _, v := range list {
			if r, ok := skuIdQtyMap[v.SkuID]; ok {
				delete(skuIdQtyMap, v.SkuID)
				v.UpdatedAt = now
				if orderId > 0 {
					v.OrderID = orderId
				}
				var qty uint64
				if r.Quantity != nil && *r.Quantity > 0 {
					qty = uint64(*r.Quantity)
				}
				v.Quantity = uint8(qty)

				if qty == 0 {
					v.Status = int8(globalkey.StatusDeleted)
				}
				err = l.svcCtx.Cart.Update(l.ctx, tx, v)
				if err != nil {
					tx.Rollback()
					return nil, resultx.StatusError(resultx.ORDER_UPDATE_CART_FAILED, "")
				}
			}
		}
	}

	for skuId, v := range skuIdQtyMap {
		if v.Quantity == nil || *v.Quantity == 0 {
			continue
		}
		var postId, inviterId uint64
		if v.PostId != nil && *v.PostId > 0 {
			postId = *v.PostId
		}
		if v.InviterId != nil && *v.InviterId > 0 {
			inviterId = *v.InviterId
		}
		cartItem := &model.CartItem{
			UserID:    userId,
			SkuID:     skuId,
			Quantity:  uint8(*v.Quantity),
			Status:    int8(globalkey.StatusEnabled),
			CreatedAt: now,
			PostID:    postId,
			InviterID: inviterId,
		}
		if orderId > 0 {
			cartItem.OrderID = orderId
		}
		err = l.svcCtx.Cart.Insert(l.ctx, tx, cartItem)
		if err != nil {
			tx.Rollback()
			return nil, resultx.StatusError(resultx.ORDER_UPDATE_CART_FAILED, "")
		}
	}

	tx.Commit()

	return &order.BaseResp{
		Msg: i18n.UpdateSuccess,
	}, nil
}
